package com.hadluo.qq.client.ui;

import com.alibaba.fastjson.JSON;
import com.hadluo.qq.client.model.Message;
import com.hadluo.qq.client.model.FriendListItem;
import com.hadluo.qq.client.model.UserInfo;
import com.hadluo.qq.client.utils.Constants;
import com.hadluo.qq.client.websocket.QQWebSocketClient;
import com.hadluo.qq.client.event.MessageEvent;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.plaf.basic.BasicScrollBarUI;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.awt.font.TextLayout;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.AttributedString;
import java.text.BreakIterator;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

public class ChatPanel extends JPanel implements QQWebSocketClient.MessageListener {
    private FriendListItem friend;
    private UserInfo currentUser;
    private JTextArea messageArea;
    private JTextArea inputArea;
    private JPanel chatHistoryPanel;
    private JScrollPane chatScrollPane;
    private SimpleDateFormat timeFormat;
    private QQWebSocketClient webSocketClient;
    private JButton shakeButton;
    private int currentPage = 1;
    private static final int PAGE_SIZE = 20;

    // 字体设置相关属性
    private String fontFamily = "Microsoft YaHei";
    private int fontSize = 14;
    private String fontColor = "#FFFFFF";
    private int fontStyle = Font.PLAIN;
    private int fontWeight = Font.PLAIN;

    // 字体设置对话框组件
    private JDialog fontDialog;
    private JComboBox<String> fontFamilyCombo;
    private JComboBox<Integer> fontSizeCombo;
    private JComboBox<String> fontStyleCombo;
    private JComboBox<String> fontWeightCombo;
    private JColorChooser colorChooser;

    // 字体设置文件
    private static final String FONT_SETTINGS_FILE = "font_settings.txt";

    public ChatPanel(FriendListItem friend, UserInfo currentUser) {
        this.friend = friend;
        this.currentUser = currentUser;
        this.timeFormat = new SimpleDateFormat("HH:mm:ss");
        this.webSocketClient = QQWebSocketClient.getInstance();
        this.webSocketClient.addMessageListener(this);
//        this.webSocketClient = QQWebSocketClient.getInstance();
//        this.webSocketClient.addMessageListener(this);
        // 加载字体设置
        loadFontSettings();

        initializeUI();
        loadHistoryMessages();
    }



    private void initializeUI() {
        setLayout(new BorderLayout());
        setBackground(new Color(35, 35, 35));

        add(createHeaderPanel(), BorderLayout.NORTH);
        add(createChatHistoryPanel(), BorderLayout.CENTER);
        add(createInputPanel(), BorderLayout.SOUTH);
    }

    private void sendShakeMessage() {
        // 检查接收方是否在线
        if (!webSocketClient.isUserOnline(friend.getQqNumber())) {
            JOptionPane.showMessageDialog(this, "对方当前不在线，无法发送抖动消息", "发送失败", JOptionPane.WARNING_MESSAGE);
            return;
        }

        Message message = new Message();
        message.setSenderId(Long.parseLong(currentUser.getQqNumber()));
        message.setReceiverId(Long.parseLong(friend.getQqNumber()));
        message.setType(Message.TYPE_SHAKE);
        message.setCreateTime(new Date());

        webSocketClient.sendMessage(message);
    }

    private JPanel createHeaderPanel() {
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setBackground(new Color(45, 45, 45));
        headerPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(60, 60, 60)),
                new EmptyBorder(10, 15, 10, 15)
        ));

        JPanel infoPanel = new JPanel(new GridLayout(2, 1, 0, 5));
        infoPanel.setBackground(new Color(45, 45, 45));

        JPanel namePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
        namePanel.setBackground(new Color(45, 45, 45));
        JLabel nicknameLabel = new JLabel(friend.getNickname());
        nicknameLabel.setForeground(Color.WHITE);
        nicknameLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
        namePanel.add(nicknameLabel);

        JLabel signatureLabel = new JLabel(friend.getSignature() != null && !friend.getSignature().isEmpty() ? friend.getSignature() : "这个人很懒，什么都没留下");
        signatureLabel.setForeground(new Color(153, 153, 153));
        signatureLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 13));

        infoPanel.add(namePanel);
        infoPanel.add(signatureLabel);

        headerPanel.add(infoPanel, BorderLayout.CENTER);

        return headerPanel;
    }

    private JScrollPane createChatHistoryPanel() {
        chatHistoryPanel = new JPanel();
        chatHistoryPanel.setLayout(new BoxLayout(chatHistoryPanel, BoxLayout.Y_AXIS));
        chatHistoryPanel.setBackground(new Color(35, 35, 35));

        chatScrollPane = new JScrollPane(chatHistoryPanel);
        chatScrollPane.setBorder(null);
        chatScrollPane.getVerticalScrollBar().setUI(new CustomScrollBarUI());
        chatScrollPane.setBackground(new Color(35, 35, 35));
        chatScrollPane.getViewport().setBackground(new Color(35, 35, 35));

        return chatScrollPane;
    }

    private JPanel createInputPanel() {
        JPanel inputPanel = new JPanel(new BorderLayout());
        inputPanel.setBackground(new Color(45, 45, 45));
        inputPanel.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createMatteBorder(1, 0, 0, 0, new Color(60, 60, 60)),
                new EmptyBorder(15, 15, 15, 15)
        ));

        JPanel functionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
        functionPanel.setBackground(new Color(45, 45, 45));

        JButton emojiButton = createFunctionButton("表情");
        emojiButton.addActionListener(e -> openEmojiChooser());
        JButton imageButton = createFunctionButton("图片");
        imageButton.addActionListener(e -> openImageChooser());
        JButton fontButton = createFunctionButton("字体");
        fontButton.addActionListener(e -> openFontSettings()); // 字体设置按钮
        shakeButton = createFunctionButton("抖动"); // 新增抖动按钮
        shakeButton.addActionListener(e -> sendShakeMessage());
        functionPanel.add(shakeButton);
//        functionPanel.add(emojiButton);
        functionPanel.add(imageButton);
        functionPanel.add(fontButton);

        inputArea = new JTextArea();
        inputArea.setBackground(new Color(35, 35, 35));
        inputArea.setForeground(Color.WHITE);
        inputArea.setCaretColor(Color.WHITE);
        inputArea.setLineWrap(true);
        inputArea.setWrapStyleWord(true);
        inputArea.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        inputArea.setRows(3);

        // 应用当前字体设置
        updateInputFont();

        JScrollPane inputScrollPane = new JScrollPane(inputArea);
        inputScrollPane.setBorder(BorderFactory.createLineBorder(new Color(60, 60, 60)));
        inputScrollPane.getVerticalScrollBar().setUI(new CustomScrollBarUI());
        inputScrollPane.setBackground(new Color(35, 35, 35));

        JButton sendButton = new JButton("发送");
        sendButton.setBackground(new Color(0, 132, 255));
        sendButton.setForeground(Color.WHITE);
        sendButton.setFocusPainted(false);
        sendButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
        sendButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        sendButton.addActionListener(e -> sendMessage());

        sendButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                sendButton.setBackground(new Color(0, 122, 235));
            }

            public void mouseExited(java.awt.event.MouseEvent evt) {
                sendButton.setBackground(new Color(0, 132, 255));
            }
        });

        JPanel bottomPanel = new JPanel(new BorderLayout(5, 0));
        bottomPanel.setBackground(new Color(45, 45, 45));
        bottomPanel.add(inputScrollPane, BorderLayout.CENTER);
        bottomPanel.add(sendButton, BorderLayout.EAST);

        inputPanel.add(functionPanel, BorderLayout.NORTH);
        inputPanel.add(bottomPanel, BorderLayout.CENTER);

        return inputPanel;
    }

    private JButton createFunctionButton(String text) {
        JButton button = new JButton(text);
        button.setBackground(new Color(245, 245, 245));
        button.setForeground(new Color(51, 51, 51));
        button.setFocusPainted(false);
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(230, 230, 230)),
                BorderFactory.createEmptyBorder(5, 10, 5, 10)
        ));

        button.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                button.setBackground(new Color(235, 235, 235));
            }

            public void mouseExited(java.awt.event.MouseEvent evt) {
                button.setBackground(new Color(245, 245, 245));
            }
        });

        return button;
    }

    private void sendMessage() {
        String content = inputArea.getText().trim();
        if (!content.isEmpty()) {
            if (!webSocketClient.isUserOnline(friend.getQqNumber())) {
                JOptionPane.showMessageDialog(this, "对方当前不在线，无法发送消息", "发送失败", JOptionPane.WARNING_MESSAGE);
                return;
            }

            try {
                // 构建包含字体信息的消息
                Map<String, Object> messageData = new HashMap<>();
                messageData.put("text", content);
                messageData.put("fontFamily", fontFamily);
                messageData.put("fontSize", fontSize);
                messageData.put("fontColor", fontColor);
                messageData.put("fontStyle", fontStyle);
                messageData.put("fontWeight", fontWeight);

                Message message = new Message();
                message.setSenderId(Long.parseLong(currentUser.getQqNumber()));
                message.setReceiverId(Long.parseLong(friend.getQqNumber()));
                message.setContent(JSON.toJSONString(messageData));
                message.setType("text");
                message.setCreateTime(new Date());
                message.setStatus(0);

                webSocketClient.sendMessage(message);
                addMessage(content, true);
                inputArea.setText("");
            } catch (Exception e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(this, "消息发送失败", "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private void addMessage(String message, boolean isCurrentUser) {
        JPanel messagePanel = new JPanel(new FlowLayout(isCurrentUser ? FlowLayout.RIGHT : FlowLayout.LEFT, 10, 0));
        messagePanel.setBackground(new Color(35, 35, 35));
        messagePanel.setBorder(new EmptyBorder(5, 15, 5, 15));
        messagePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));

        JLabel avatarLabel = new JLabel();
        avatarLabel.setPreferredSize(new Dimension(40, 40));
        avatarLabel.setBackground(new Color(35, 35, 35));
        avatarLabel.setOpaque(true);

        String avatarUrl = isCurrentUser ? currentUser.getAvatar() : friend.getAvatar();
        if (avatarUrl != null && !avatarUrl.isEmpty()) {
            try {
                if (!avatarUrl.startsWith("http")) {
                    avatarUrl = "http://"+Constants.SERVER_HOST+":8080" + avatarUrl;
                }
                ImageIcon imageIcon = new ImageIcon(new URL(avatarUrl));
                Image image = imageIcon.getImage().getScaledInstance(40, 40, Image.SCALE_SMOOTH);
                avatarLabel.setIcon(new ImageIcon(image));
            } catch (Exception e) {
                String avatarText = isCurrentUser ? currentUser.getNickname().substring(0, 1) : friend.getNickname().substring(0, 1);
                avatarLabel.setText(avatarText);
                avatarLabel.setHorizontalAlignment(SwingConstants.CENTER);
                avatarLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
                avatarLabel.setForeground(new Color(51, 51, 51));
            }
        } else {
            String avatarText = isCurrentUser ? currentUser.getNickname().substring(0, 1) : friend.getNickname().substring(0, 1);
            avatarLabel.setText(avatarText);
            avatarLabel.setHorizontalAlignment(SwingConstants.CENTER);
            avatarLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
            avatarLabel.setForeground(new Color(51, 51, 51));
        }

        JPanel contentPanel = new JPanel(new BorderLayout(0, 3));
        contentPanel.setBackground(new Color(35, 35, 35));
        contentPanel.setOpaque(false);

        JLabel timeLabel = new JLabel(timeFormat.format(new Date()));
        timeLabel.setForeground(new Color(153, 153, 153));
        timeLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
        timeLabel.setBorder(new EmptyBorder(0, isCurrentUser ? 0 : 8, 2, isCurrentUser ? 8 : 0));

        JTextArea messageArea = new JTextArea(message);

        // 应用字体设置
        Font messageFont = new Font(fontFamily, fontStyle, fontSize);
        messageArea.setFont(messageFont);
        messageArea.setForeground(Color.decode(fontColor));
        messageArea.setLineWrap(true);
        messageArea.setWrapStyleWord(true);
        messageArea.setEditable(false);
        messageArea.setOpaque(false);
        messageArea.setBorder(BorderFactory.createEmptyBorder(12, 15, 12, 15));

        int maxWidth = 400;
        int padding = 20;
        int minHeight = 30;
        FontRenderContext frc = new FontRenderContext(null, true, true);
        Font font = messageArea.getFont();
        int totalHeight = 0;
        BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        FontMetrics fm = g2d.getFontMetrics(font);

        String[] paragraphs = message.split("\n");
        for (String paragraph : paragraphs) {
            if (paragraph.isEmpty()) {
                totalHeight += fm.getHeight();
                continue;
            }
            int availableWidth = maxWidth - padding * 2;
            AttributedString attributedString = new AttributedString(paragraph);
            attributedString.addAttribute(TextAttribute.FONT, font);
            LineBreakMeasurer measurer = new LineBreakMeasurer(
                    attributedString.getIterator(),
                    BreakIterator.getLineInstance(),
                    frc
            );
            measurer.setPosition(0);
            while (measurer.getPosition() < paragraph.length()) {
                TextLayout layout = measurer.nextLayout(availableWidth);
                totalHeight += layout.getAscent() + layout.getDescent() + layout.getLeading();
            }
            totalHeight += 5;
        }
        g2d.dispose();

        totalHeight += padding * 2;
        totalHeight = Math.max(totalHeight, minHeight);
        int contentWidth = Math.min(maxWidth, fm.stringWidth(message) + padding * 2);
        contentWidth = Math.max(contentWidth, 100);

        messageArea.setSize(contentWidth, totalHeight);
        messageArea.setPreferredSize(new Dimension(contentWidth, totalHeight));

        JPanel bubblePanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                int width = getWidth();
                int height = getHeight();
                int radius = 15;

                GradientPaint gradient;
                if (isCurrentUser) {
                    gradient = new GradientPaint(
                            0, 0, new Color(0, 132, 255),
                            width, height, new Color(0, 122, 235)
                    );
                } else {
                    gradient = new GradientPaint(
                            0, 0, new Color(45, 45, 45),
                            width, height, new Color(55, 55, 55)
                    );
                }

                g2.setColor(new Color(0, 0, 0, 30));
                g2.fillRoundRect(2, 2, width - 2, height - 2, radius, radius);
                g2.setColor(new Color(0, 0, 0, 15));
                g2.fillRoundRect(1, 1, width - 1, height - 1, radius, radius);

                RoundRectangle2D bubble = new RoundRectangle2D.Float(0, 0, width - 3, height - 3, radius, radius);
                g2.setPaint(gradient);
                g2.fill(bubble);

                g2.dispose();
            }
        };
        bubblePanel.setOpaque(false);
        bubblePanel.setLayout(new BorderLayout());
        bubblePanel.add(messageArea, BorderLayout.CENTER);

        if (isCurrentUser) {
            messageArea.setForeground(Color.WHITE);
        } else {
            messageArea.setForeground(new Color(220, 220, 220));
        }

        contentPanel.add(timeLabel, BorderLayout.NORTH);
        contentPanel.add(bubblePanel, BorderLayout.CENTER);

        if (isCurrentUser) {
            messagePanel.add(contentPanel);
            messagePanel.add(avatarLabel);
        } else {
            messagePanel.add(avatarLabel);
            messagePanel.add(contentPanel);
        }

        chatHistoryPanel.add(messagePanel);
        chatHistoryPanel.revalidate();

        SwingUtilities.invokeLater(() -> {
            JScrollBar vertical = chatScrollPane.getVerticalScrollBar();
            vertical.setValue(vertical.getMaximum());
        });
    }

    private void openImageChooser() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new FileNameExtensionFilter("图片文件", "jpg", "jpeg", "png", "gif"));

        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            sendImage(selectedFile);
        }
    }

    private void sendImage(File imageFile) {
        try {
            long fileSize = imageFile.length();
            if (fileSize > 5 * 1024 * 1024) {
                JOptionPane.showMessageDialog(this, "图片大小不能超过5MB", "发送失败", JOptionPane.WARNING_MESSAGE);
                return;
            }

            if (!webSocketClient.isUserOnline(friend.getQqNumber())) {
                JOptionPane.showMessageDialog(this, "对方当前不在线，无法发送图片", "发送失败", JOptionPane.WARNING_MESSAGE);
                return;
            }

            String uploadUrl = "http://"+Constants.SERVER_HOST+":8080/api/file/upload";
            HttpURLConnection conn = (HttpURLConnection) new URL(uploadUrl).openConnection();
            conn.setRequestMethod("POST");
            String boundary = "----WebKitFormBoundary" + System.currentTimeMillis();
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            conn.setDoOutput(true);

            try (OutputStream os = conn.getOutputStream()) {
                os.write(("--" + boundary + "\r\n").getBytes("UTF-8"));
                String fileHeader = "Content-Disposition: form-data; name=\"file\"; filename=\""
                        + imageFile.getName() + "\"\r\n";
                os.write(fileHeader.getBytes("UTF-8"));
                os.write("Content-Type: image/jpeg\r\n\r\n".getBytes("UTF-8"));
                Files.copy(imageFile.toPath(), os);
                os.write("\r\n".getBytes("UTF-8"));
                os.write(("--" + boundary + "--\r\n").getBytes("UTF-8"));
            }

            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
                String response = in.readLine();
                in.close();

                Map<String, Object> result = JSON.parseObject(response);
                String imageUrl = (String) result.get("url");

                Message message = new Message();
                message.setSenderId(Long.parseLong(currentUser.getQqNumber()));
                message.setReceiverId(Long.parseLong(friend.getQqNumber()));
                message.setContent(imageUrl);
                message.setType("image");
                message.setCreateTime(new Date());
                message.setStatus(0);

                webSocketClient.sendMessage(message);
                addImageMessage(imageUrl, true);
            } else {
                throw new IOException("服务器返回错误代码：" + responseCode);
            }
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "图片发送失败：" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void addImageMessage(String imageUrl, boolean isCurrentUser) {
        try {
            if (!imageUrl.startsWith("http")) {
                imageUrl = "http://"+Constants.SERVER_HOST+":8080" + imageUrl;
            }
            ImageIcon imageIcon = new ImageIcon(new URL(imageUrl));

            Image image = imageIcon.getImage();
            int maxWidth = 300;
            int maxHeight = 300;

            int width = image.getWidth(null);
            int height = image.getHeight(null);

            if (width > maxWidth || height > maxHeight) {
                double scale = Math.min((double) maxWidth / width, (double) maxHeight / height);
                width = (int) (width * scale);
                height = (int) (height * scale);
            }

            Image scaledImage = image.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            ImageIcon scaledIcon = new ImageIcon(scaledImage);

            JLabel imageLabel = new JLabel(scaledIcon);
            imageLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

            JPanel messagePanel = new JPanel(new FlowLayout(isCurrentUser ? FlowLayout.RIGHT : FlowLayout.LEFT, 10, 0));
            messagePanel.setBackground(new Color(35, 35, 35));
            messagePanel.setBorder(new EmptyBorder(5, 15, 5, 15));

            JLabel avatarLabel = new JLabel();
            avatarLabel.setPreferredSize(new Dimension(40, 40));
            avatarLabel.setBackground(new Color(35, 35, 35));
            avatarLabel.setOpaque(true);

            String avatarUrl = isCurrentUser ? currentUser.getAvatar() : friend.getAvatar();
            if (avatarUrl != null && !avatarUrl.isEmpty()) {
                try {
                    if (!avatarUrl.startsWith("http")) {
                        avatarUrl = "http://"+Constants.SERVER_HOST+":8080" + avatarUrl;
                    }
                    ImageIcon avatar = new ImageIcon(new URL(avatarUrl));
                    Image avatarImage = avatar.getImage().getScaledInstance(40, 40, Image.SCALE_SMOOTH);
                    avatarLabel.setIcon(new ImageIcon(avatarImage));
                } catch (Exception e) {
                    String avatarText = isCurrentUser ? currentUser.getNickname().substring(0, 1) : friend.getNickname().substring(0, 1);
                    avatarLabel.setText(avatarText);
                    avatarLabel.setHorizontalAlignment(SwingConstants.CENTER);
                    avatarLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
                    avatarLabel.setForeground(new Color(51, 51, 51));
                }
            }

            JPanel contentPanel = new JPanel(new BorderLayout(0, 3));
            contentPanel.setBackground(new Color(35, 35, 35));
            contentPanel.setOpaque(false);

            JLabel timeLabel = new JLabel(timeFormat.format(new Date()));
            timeLabel.setForeground(new Color(153, 153, 153));
            timeLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
            timeLabel.setBorder(new EmptyBorder(0, isCurrentUser ? 0 : 8, 2, isCurrentUser ? 8 : 0));

            JPanel bubblePanel = new JPanel() {
                @Override
                protected void paintComponent(Graphics g) {
                    Graphics2D g2 = (Graphics2D) g.create();
                    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                    int width = getWidth();
                    int height = getHeight();
                    int radius = 15;

                    GradientPaint gradient;
                    if (isCurrentUser) {
                        gradient = new GradientPaint(
                                0, 0, new Color(0, 132, 255),
                                width, height, new Color(0, 122, 235)
                        );
                    } else {
                        gradient = new GradientPaint(
                                0, 0, new Color(45, 45, 45),
                                width, height, new Color(55, 55, 55)
                        );
                    }

                    g2.setColor(new Color(0, 0, 0, 30));
                    g2.fillRoundRect(2, 2, width - 2, height - 2, radius, radius);
                    g2.setColor(new Color(0, 0, 0, 15));
                    g2.fillRoundRect(1, 1, width - 1, height - 1, radius, radius);

                    RoundRectangle2D bubble = new RoundRectangle2D.Float(0, 0, width - 3, height - 3, radius, radius);
                    g2.setPaint(gradient);
                    g2.fill(bubble);

                    g2.dispose();
                }
            };
            bubblePanel.setOpaque(false);
            bubblePanel.setLayout(new BorderLayout());
            bubblePanel.add(imageLabel, BorderLayout.CENTER);

            contentPanel.add(timeLabel, BorderLayout.NORTH);
            contentPanel.add(bubblePanel, BorderLayout.CENTER);

            if (isCurrentUser) {
                messagePanel.add(contentPanel);
                messagePanel.add(avatarLabel);
            } else {
                messagePanel.add(avatarLabel);
                messagePanel.add(contentPanel);
            }

            chatHistoryPanel.add(messagePanel);
            chatHistoryPanel.revalidate();

            SwingUtilities.invokeLater(() -> {
                JScrollBar vertical = chatScrollPane.getVerticalScrollBar();
                vertical.setValue(vertical.getMaximum());
            });
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "图片显示失败：" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void loadHistoryMessages() {
        new Thread(() -> {
            try {
                String url = String.format("http://"+ Constants.SERVER_HOST+":8080/api/messages/history?senderId=%s&receiverId=%s&page=1&size=50",
                        currentUser.getQqNumber(), friend.getQqNumber());

                HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
                conn.setRequestMethod("GET");
                conn.setRequestProperty("Content-Type", "application/json");
                conn.setConnectTimeout(5000);
                conn.setReadTimeout(5000);

                if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    try (BufferedReader br = new BufferedReader(
                            new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = br.readLine()) != null) {
                            response.append(line);
                        }

                        List<Message> messages = JSON.parseArray(response.toString(), Message.class);
                        if (messages != null && !messages.isEmpty()) {
                            Collections.sort(messages, (m1, m2) ->
                                    m1.getCreateTime().compareTo(m2.getCreateTime()));

                            for (Message message : messages) {
                                boolean isCurrentUser = message.getSenderId().equals(
                                        Long.parseLong(currentUser.getQqNumber()));
                                SwingUtilities.invokeLater(() -> {
                                    if ("image".equals(message.getType())) {
                                        addImageMessage(message.getContent(), isCurrentUser);
                                    } else {
                                        try {
                                            // 解析消息中的字体信息
                                            Map<String, Object> messageData = JSON.parseObject(message.getContent(), Map.class);
                                            String text = (String) messageData.get("text");
                                            addMessage(text, isCurrentUser);
                                        } catch (Exception e) {
                                            addMessage(message.getContent(), isCurrentUser);
                                        }
                                    }
                                });
                            }

                            SwingUtilities.invokeLater(() -> {
                                JScrollBar vertical = chatScrollPane.getVerticalScrollBar();
                                vertical.setValue(vertical.getMaximum());
                            });
                        }
                    }
                } else {
                    System.err.println("Failed to load history messages: " + conn.getResponseCode());
                }
            } catch (Exception e) {
                System.err.println("Error loading history messages: " + e.getMessage());
                e.printStackTrace();
            }
        }).start();
    }

    @Override
    public void onMessageReceived(MessageEvent event) {
        Message message = event.getMessage();
        if (message != null && Message.TYPE_SHAKE.equals(message.getType())) {
            // 实现抖动效果
            shakeWindow();
        }
        if (message == null) {
            return;
        }
        if (message.getSenderId().equals(Long.parseLong(friend.getQqNumber()))) {
            SwingUtilities.invokeLater(() -> {
                Toolkit.getDefaultToolkit().beep();
                if ("image".equals(message.getType())) {
                    addImageMessage(message.getContent(), false);
                } else {
                    try {
                        // 解析消息中的字体信息
                        Map<String, Object> messageData = JSON.parseObject(message.getContent(), Map.class);
                        String text = (String) messageData.get("text");
                        addMessage(text, false);
                    } catch (Exception e) {
                        addMessage(message.getContent(), false);
                    }
                }
            });
        }
    }

    private void shakeWindow() {
        JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(this);
        Point originalLocation = frame.getLocation();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            int x = originalLocation.x + random.nextInt(10) - 5;
            int y = originalLocation.y + random.nextInt(10) - 5;
            frame.setLocation(x, y);
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        frame.setLocation(originalLocation);
    }

    private static class CustomScrollBarUI extends BasicScrollBarUI {
        @Override
        protected JButton createDecreaseButton(int orientation) {
            return createZeroButton();
        }

        @Override
        protected JButton createIncreaseButton(int orientation) {
            return createZeroButton();
        }

        private JButton createZeroButton() {
            JButton button = new JButton();
            button.setPreferredSize(new Dimension(0, 0));
            return button;
        }

        @Override
        protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
            if (thumbBounds.isEmpty() || !scrollbar.isEnabled()) {
                return;
            }

            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setColor(new Color(200, 200, 200));
            g2.fillRoundRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, 8, 8);
            g2.dispose();
        }

        @Override
        protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setColor(new Color(245, 245, 245));
            g2.fillRect(trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height);
            g2.dispose();
        }
    }

    private void openEmojiChooser() {
        JDialog emojiDialog = new JDialog((Frame) SwingUtilities.getWindowAncestor(this), "选择表情", true);
        emojiDialog.setLayout(new BorderLayout());

        JPanel emojiPanel = new JPanel(new GridLayout(3, 5, 5, 5));
        emojiPanel.setBackground(new Color(45, 45, 45));
        emojiPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        String[] emojis = {"😊", "😂", "🤣", "😅", "😆", "😍", "😘", "🥰", "😎", "🤔", "😏", "😣", "😥", "😪"};

        for (String emoji : emojis) {
            JButton emojiButton = new JButton(emoji);
            emojiButton.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 24));
            emojiButton.setBackground(new Color(35, 35, 35));
            emojiButton.setForeground(Color.WHITE);
            emojiButton.setBorder(BorderFactory.createLineBorder(new Color(60, 60, 60)));
            emojiButton.setFocusPainted(false);

            emojiButton.addMouseListener(new java.awt.event.MouseAdapter() {
                public void mouseEntered(java.awt.event.MouseEvent evt) {
                    emojiButton.setBackground(new Color(55, 55, 55));
                }

                public void mouseExited(java.awt.event.MouseEvent evt) {
                    emojiButton.setBackground(new Color(35, 35, 35));
                }
            });

            emojiButton.addActionListener(e -> {
                inputArea.insert(emoji, inputArea.getCaretPosition());
                emojiDialog.dispose();
            });

            emojiPanel.add(emojiButton);
        }

        emojiDialog.add(emojiPanel, BorderLayout.CENTER);
        emojiDialog.pack();
        emojiDialog.setLocationRelativeTo(this);
        emojiDialog.setVisible(true);
    }

    // 字体设置相关功能
    private void openFontSettings() {
        if (fontDialog == null) {
            fontDialog = new JDialog((Frame) SwingUtilities.getWindowAncestor(this), "字体设置", true);
            fontDialog.setLayout(new BorderLayout(10, 10));
            fontDialog.setSize(400, 320);
            fontDialog.setLocationRelativeTo(this);

            // 创建字体设置面板
            JPanel settingsPanel = new JPanel(new GridLayout(0, 2, 10, 10));
            settingsPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
            settingsPanel.setBackground(new Color(45, 45, 45));

            // 获取系统可用字体
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            String[] availableFonts = ge.getAvailableFontFamilyNames();

            // 字体选择
            settingsPanel.add(new JLabel("字体:", JLabel.RIGHT));
            fontFamilyCombo = new JComboBox<>(availableFonts);
            fontFamilyCombo.setSelectedItem(fontFamily);
            settingsPanel.add(fontFamilyCombo);

            // 字号选择
            settingsPanel.add(new JLabel("字号:", JLabel.RIGHT));
            Integer[] fontSizes = {8, 10, 12, 14, 16, 18, 20, 24, 28, 36};
            fontSizeCombo = new JComboBox<>(fontSizes);
            fontSizeCombo.setSelectedItem(fontSize);
            settingsPanel.add(fontSizeCombo);

            // 字体样式
            settingsPanel.add(new JLabel("样式:", JLabel.RIGHT));
            String[] fontStyles = {"常规", "斜体"};
            fontStyleCombo = new JComboBox<>(fontStyles);
            fontStyleCombo.setSelectedItem(fontStyle == Font.ITALIC ? "斜体" : "常规");
            settingsPanel.add(fontStyleCombo);

            // 字体粗细
            settingsPanel.add(new JLabel("粗细:", JLabel.RIGHT));
            String[] fontWeights = {"普通", "粗体"};
            fontWeightCombo = new JComboBox<>(fontWeights);
            fontWeightCombo.setSelectedItem(fontWeight == Font.BOLD ? "粗体" : "普通");
            settingsPanel.add(fontWeightCombo);

//            // 字体颜色
//            settingsPanel.add(new JLabel("颜色:", JLabel.RIGHT));
//            colorChooser = new JColorChooser();
//            colorChooser.setColor(Color.decode(fontColor));
//            settingsPanel.add(colorChooser);

            // 按钮面板
            JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
            buttonPanel.setBackground(new Color(45, 45, 45));

            JButton applyButton = new JButton("应用");
            applyButton.addActionListener(e -> applyFontSettings());
            JButton cancelButton = new JButton("取消");
            cancelButton.addActionListener(e -> fontDialog.dispose());

            buttonPanel.add(applyButton);
            buttonPanel.add(cancelButton);

            // 添加到对话框
            fontDialog.add(settingsPanel, BorderLayout.CENTER);
            fontDialog.add(buttonPanel, BorderLayout.SOUTH);
        }

        fontDialog.setVisible(true);
    }

    private void applyFontSettings() {
        try {
            // 获取选择的字体设置
            fontFamily = (String) fontFamilyCombo.getSelectedItem();
            fontSize = (Integer) fontSizeCombo.getSelectedItem();
            fontStyle = "斜体".equals(fontStyleCombo.getSelectedItem()) ? Font.ITALIC : Font.PLAIN;
            fontWeight = "粗体".equals(fontWeightCombo.getSelectedItem()) ? Font.BOLD : Font.PLAIN;
//            Color selectedColor = colorChooser.getColor();
//            fontColor = String.format("#%02x%02x%02x",
//                    selectedColor.getRed(), selectedColor.getGreen(), selectedColor.getBlue());

            // 更新输入框字体
            updateInputFont();

            // 保存字体设置
            saveFontSettings();

            fontDialog.dispose();
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "字体设置应用失败", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void updateInputFont() {
        inputArea.setFont(new Font(fontFamily, fontStyle | fontWeight, fontSize));
        inputArea.setForeground(Color.decode(fontColor));
    }

    private void saveFontSettings() {
        try (FileWriter fw = new FileWriter(FONT_SETTINGS_FILE);
             BufferedWriter bw = new BufferedWriter(fw)) {
            bw.write(fontFamily);
            bw.newLine();
            bw.write(String.valueOf(fontSize));
            bw.newLine();
            bw.write(String.valueOf(fontStyle));
            bw.newLine();
            bw.write(String.valueOf(fontWeight));
            bw.newLine();
            bw.write(fontColor);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadFontSettings() {
        File settingsFile = new File(FONT_SETTINGS_FILE);
        if (settingsFile.exists()) {
            try (FileReader fr = new FileReader(settingsFile);
                 BufferedReader br = new BufferedReader(fr)) {
                fontFamily = br.readLine();
                fontSize = Integer.parseInt(br.readLine());
                fontStyle = Integer.parseInt(br.readLine());
                fontWeight = Integer.parseInt(br.readLine());
                fontColor = br.readLine();

                // 确保字体存在，否则使用默认字体
                if (!isFontAvailable(fontFamily)) {
                    fontFamily = "Microsoft YaHei";
                }
            } catch (Exception e) {
                e.printStackTrace();
                // 使用默认字体设置
                fontFamily = "Microsoft YaHei";
                fontSize = 14;
                fontStyle = Font.PLAIN;
                fontWeight = Font.PLAIN;
                fontColor = "#FFFFFF";
            }
        }
    }

    private boolean isFontAvailable(String fontFamily) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        return Arrays.asList(ge.getAvailableFontFamilyNames()).contains(fontFamily);
    }
}